home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / srcuc.zip / UXSIG.C < prev    next >
C/C++ Source or Header  |  1992-02-27  |  35KB  |  1,258 lines

  1. /* -*-C-*-
  2.  
  3. $Header: /scheme/src/microcode/RCS/uxsig.c,v 1.22 1992/02/27 18:54:43 mhwu Exp $
  4.  
  5. Copyright (c) 1990-92 Massachusetts Institute of Technology
  6.  
  7. This material was developed by the Scheme project at the Massachusetts
  8. Institute of Technology, Department of Electrical Engineering and
  9. Computer Science.  Permission to copy this software, to redistribute
  10. it, and to use it for any purpose is granted, subject to the following
  11. restrictions and understandings.
  12.  
  13. 1. Any copy made of this software must include this copyright notice
  14. in full.
  15.  
  16. 2. Users of this software agree to make their best efforts (a) to
  17. return to the MIT Scheme project any improvements or extensions that
  18. they make, so that these may be included in future releases; and (b)
  19. to inform MIT of noteworthy uses of this software.
  20.  
  21. 3. All materials developed as a consequence of the use of this
  22. software shall duly acknowledge such use, in accordance with the usual
  23. standards of acknowledging credit in academic research.
  24.  
  25. 4. MIT has made no warrantee or representation that the operation of
  26. this software will be error-free, and MIT is under no obligation to
  27. provide any services, by way of maintenance, update, or otherwise.
  28.  
  29. 5. In conjunction with products arising from the use of this material,
  30. there shall be no use of the name of the Massachusetts Institute of
  31. Technology nor of any adaptation thereof in any advertising,
  32. promotional, or sales literature without prior written consent from
  33. MIT in each case. */
  34.  
  35. #include "ux.h"
  36. #include "ossig.h"
  37. #include "osctty.h"
  38. #include "ostty.h"
  39. #include "uxtrap.h"
  40. #include "uxutil.h"
  41. #include "critsec.h"
  42.  
  43. /* Signal Manipulation */
  44.  
  45. #ifdef HAVE_POSIX_SIGNALS
  46.  
  47. static Tsignal_handler
  48. DEFUN (current_handler, (signo), int signo)
  49. {
  50.   struct sigaction act;
  51.   UX_sigaction (signo, 0, (&act));
  52.   return (act . sa_handler);
  53. }
  54.  
  55. #ifndef SA_SIGINFO
  56. #define SA_SIGINFO 0
  57. #endif
  58.  
  59. static void
  60. DEFUN (INSTALL_HANDLER, (signo, handler),
  61.        int signo AND
  62.        Tsignal_handler handler)
  63. {
  64.   struct sigaction act;
  65.   (act . sa_handler) = handler;
  66.   UX_sigemptyset (& (act . sa_mask));
  67.   UX_sigaddset ((& (act . sa_mask)), signo);
  68.   (act . sa_flags) = SA_SIGINFO;
  69.   UX_sigaction (signo, (&act), 0);
  70. }
  71.  
  72. #else /* not HAVE_POSIX_SIGNALS */
  73. #ifdef HAVE_SYSV3_SIGNALS
  74.  
  75. static Tsignal_handler
  76. DEFUN (current_handler, (signo), int signo)
  77. {
  78.   Tsignal_handler result = (UX_sigset (signo, SIG_HOLD));
  79.   if (result != SIG_HOLD)
  80.     UX_signal (signo, result);
  81.   return (result);
  82. }
  83.  
  84. #define INSTALL_HANDLER UX_sigset
  85.  
  86. #define NEED_HANDLER_TRANSACTION
  87. #define ENTER_HANDLER(signo)
  88. #define ABORT_HANDLER(signo, handler) UX_sigrelse (signo)
  89. #define EXIT_HANDLER(signo, handler)
  90.  
  91. #else /* not HAVE_SYSV3_SIGNALS */
  92.  
  93. static Tsignal_handler
  94. DEFUN (current_handler, (signo), int signo)
  95. {
  96.   Tsignal_handler result = (UX_signal (signo, SIG_IGN));
  97.   if (result != SIG_IGN)
  98.     UX_signal (signo, result);
  99.   return (result);
  100. }
  101.  
  102. #define INSTALL_HANDLER UX_signal
  103.  
  104. #define NEED_HANDLER_TRANSACTION
  105. #define ENTER_HANDLER(signo) UX_signal ((signo), SIG_IGN)
  106. #define ABORT_HANDLER UX_signal
  107. #define EXIT_HANDLER UX_signal
  108.  
  109. #endif /* HAVE_SYSV3_SIGNALS */
  110. #endif /* HAVE_POSIX_SIGNALS */
  111.  
  112. #ifdef HAVE_POSIX_SIGNALS
  113.  
  114. static void
  115. DEFUN (restore_signal_mask, (environment), PTR environment)
  116. {
  117.   UX_sigprocmask (SIG_SETMASK, ((sigset_t *) environment), 0);
  118. }
  119.  
  120. static void
  121. DEFUN (save_signal_mask, (environment), PTR environment)
  122. {
  123.   UX_sigprocmask (SIG_SETMASK, 0, ((sigset_t *) environment));
  124. }
  125.  
  126. void
  127. DEFUN_VOID (preserve_signal_mask)
  128. {
  129.   dstack_alloc_and_protect
  130.     ((sizeof (sigset_t)), save_signal_mask, restore_signal_mask);
  131. }
  132.  
  133. static sigset_t blocked_signals;
  134.  
  135. void
  136. DEFUN_VOID (block_signals)
  137. {
  138.   sigset_t all_signals;
  139.   UX_sigfillset (&all_signals);
  140.   UX_sigprocmask (SIG_BLOCK, (&all_signals), (&blocked_signals));
  141. }
  142.  
  143. void
  144. DEFUN_VOID (unblock_signals)
  145. {
  146.   UX_sigprocmask (SIG_SETMASK, (&blocked_signals), 0);
  147. }
  148.  
  149. #else /* not HAVE_POSIX_SIGNALS */
  150.  
  151. void
  152. DEFUN_VOID (preserve_signal_mask)
  153. {
  154. }
  155.  
  156. void
  157. DEFUN_VOID (block_signals)
  158. {
  159. }
  160.  
  161. void
  162. DEFUN_VOID (unblock_signals)
  163. {
  164. }
  165.  
  166. #endif /* not HAVE_POSIX_SIGNALS */
  167.  
  168. /* Signal Descriptors */
  169.  
  170. enum dfl_action { dfl_terminate, dfl_ignore, dfl_stop };
  171.  
  172. struct signal_descriptor
  173. {
  174.   int signo;
  175.   CONST char * name;
  176.   enum dfl_action action;
  177.   int flags;
  178. };
  179.  
  180. /* `flags' bits */
  181. #define NOIGNORE 1
  182. #define NOBLOCK 2
  183. #define NOCATCH 4
  184. #define CORE_DUMP 8
  185.  
  186. static struct signal_descriptor * signal_descriptors;
  187. static unsigned int signal_descriptors_length;
  188. static unsigned int signal_descriptors_limit;
  189.  
  190. static void
  191. DEFUN (defsignal, (signo, name, action, flags),
  192.        int signo AND
  193.        CONST char * name AND
  194.        enum dfl_action action AND
  195.        int flags)
  196. {
  197.   if (signo == 0)
  198.     return;
  199.   if (signal_descriptors_length == signal_descriptors_limit)
  200.     {
  201.       signal_descriptors_limit += 8;
  202.       signal_descriptors =
  203.     (UX_realloc (signal_descriptors,
  204.              (signal_descriptors_limit *
  205.               (sizeof (struct signal_descriptor)))));
  206.       if (signal_descriptors == 0)
  207.     {
  208.       fprintf (stderr, "\nUnable to grow signal definitions table.\n");
  209.       fflush (stderr);
  210.       termination_init_error ();
  211.     }
  212.     }
  213.   {
  214.     struct signal_descriptor * sd =
  215.       (signal_descriptors + (signal_descriptors_length++));
  216.     (sd -> signo) = signo;
  217.     (sd -> name) = name;
  218.     (sd -> action) = action;
  219.     (sd -> flags) = flags;
  220.   }
  221. }
  222.  
  223. static struct signal_descriptor *
  224. DEFUN (find_signal_descriptor, (signo), int signo)
  225. {
  226.   struct signal_descriptor * scan = signal_descriptors;
  227.   struct signal_descriptor * end = (scan + signal_descriptors_length);
  228.   for (; (scan < end); scan += 1)
  229.     if ((scan -> signo) == signo)
  230.       return (scan);
  231.   return (0);
  232. }
  233.  
  234. CONST char *
  235. DEFUN (find_signal_name, (signo), int signo)
  236. {
  237.   static char buffer [32];
  238.   struct signal_descriptor * descriptor = (find_signal_descriptor (signo));
  239.   if (descriptor != 0)
  240.     return (descriptor -> name);
  241.   sprintf (buffer, "unknown signal %d", signo);
  242.   return ((CONST char *) buffer);
  243. }
  244.  
  245. #ifdef _HPUX
  246.  
  247. #define OS_SPECIFIC_SIGNALS()                        \
  248. {                                    \
  249.   defsignal (SIGPWR, "SIGPWR",        dfl_ignore,    0);        \
  250.   defsignal (SIGWINDOW, "SIGWINDOW",    dfl_ignore,    0);        \
  251.   defsignal (SIGLOST, "SIGLOST",    dfl_terminate,    0);        \
  252. }
  253.  
  254. #else /* not _HPUX */
  255. #ifdef _BSD
  256.  
  257. #define OS_SPECIFIC_SIGNALS()                        \
  258. {                                    \
  259.   defsignal (SIGXCPU, "SIGXCPU",    dfl_terminate,    0);        \
  260.   defsignal (SIGXFSZ, "SIGXFSZ",    dfl_terminate,    0);        \
  261.   defsignal (SIGWINCH, "SIGWINCH",    dfl_ignore,    0);        \
  262. }
  263.  
  264. #endif /* _BSD */
  265. #endif /* _HPUX */
  266.  
  267. #if (SIGABRT == SIGIOT)
  268. #undef SIGABRT
  269. #define SIGABRT 0
  270. #endif
  271.  
  272. static void
  273. DEFUN_VOID (initialize_signal_descriptors)
  274. {
  275.   signal_descriptors_length = 0;
  276.   signal_descriptors_limit = 32;
  277.   signal_descriptors =
  278.     (UX_malloc (signal_descriptors_limit *
  279.         (sizeof (struct signal_descriptor))));
  280.   if (signal_descriptors == 0)
  281.     {
  282.       fprintf (stderr, "\nUnable to allocate signal definitions table.\n");
  283.       fflush (stderr);
  284.       termination_init_error ();
  285.     }
  286.   defsignal (SIGHUP, "SIGHUP",        dfl_terminate,    0);
  287.   defsignal (SIGINT, "SIGINT",        dfl_terminate,    0);
  288.   defsignal (SIGQUIT, "SIGQUIT",    dfl_terminate,    CORE_DUMP);
  289.   defsignal (SIGILL, "SIGILL",        dfl_terminate,    CORE_DUMP);
  290.   defsignal (SIGTRAP, "SIGTRAP",    dfl_terminate,    CORE_DUMP);
  291.   defsignal (SIGIOT, "SIGIOT",        dfl_terminate,    CORE_DUMP);
  292.   defsignal (SIGEMT, "SIGEMT",        dfl_terminate,    CORE_DUMP);
  293.   defsignal (SIGFPE, "SIGFPE",        dfl_terminate,    CORE_DUMP);
  294.   defsignal (SIGKILL, "SIGKILL",    dfl_terminate,    (NOIGNORE | NOBLOCK | NOCATCH));
  295.   defsignal (SIGBUS, "SIGBUS",        dfl_terminate,    CORE_DUMP);
  296.   defsignal (SIGSEGV, "SIGSEGV",    dfl_terminate,    CORE_DUMP);
  297.   defsignal (SIGSYS, "SIGSYS",        dfl_terminate,    CORE_DUMP);
  298.   defsignal (SIGPIPE, "SIGPIPE",    dfl_terminate,    0);
  299.   defsignal (SIGALRM, "SIGALRM",    dfl_terminate,    0);
  300.   defsignal (SIGTERM, "SIGTERM",    dfl_terminate,    0);
  301.   defsignal (SIGUSR1, "SIGUSR1",    dfl_terminate,    0);
  302.   defsignal (SIGUSR2, "SIGUSR2",    dfl_terminate,    0);
  303.   defsignal (SIGABRT, "SIGABRT",    dfl_terminate,    CORE_DUMP);
  304.   defsignal (SIGIO, "SIGIO",        dfl_ignore,    0);
  305.   defsignal (SIGURG, "SIGURG",        dfl_ignore,    0);
  306.   defsignal (SIGVTALRM, "SIGVTALRM",    dfl_terminate,    0);
  307.   defsignal (SIGPROF, "SIGPROF",    dfl_terminate,    0);
  308.   defsignal (SIGSTOP, "SIGSTOP",    dfl_stop,    (NOIGNORE | NOBLOCK | NOCATCH));
  309.   defsignal (SIGTSTP, "SIGTSTP",    dfl_stop,    0);
  310.   defsignal (SIGCONT, "SIGCONT",    dfl_ignore,    (NOIGNORE | NOBLOCK));
  311.   defsignal (SIGCHLD, "SIGCHLD",    dfl_ignore,    0);
  312.   defsignal (SIGTTIN, "SIGTTIN",    dfl_stop,    0);
  313.   defsignal (SIGTTOU, "SIGTTOU",    dfl_stop,    0);
  314. #ifdef OS_SPECIFIC_SIGNALS
  315.   OS_SPECIFIC_SIGNALS ();
  316. #endif
  317. }
  318.  
  319. /* Signal Handlers */
  320.  
  321. #ifndef NEED_HANDLER_TRANSACTION
  322.  
  323. #define DEFUN_STD_HANDLER(name, statement)                \
  324. static Tsignal_handler_result                        \
  325. DEFUN (name, (signo, info, pscp),                    \
  326.        int signo AND                            \
  327.        SIGINFO_T info AND                        \
  328.        struct SIGCONTEXT * pscp)                    \
  329. {                                    \
  330.   int STD_HANDLER_abortp;                        \
  331.   DECLARE_FULL_SIGCONTEXT (scp);                    \
  332.   INITIALIZE_FULL_SIGCONTEXT (pscp, scp);                \
  333.   STD_HANDLER_abortp = (enter_interruption_extent ());            \
  334.   statement;                                \
  335.   if (STD_HANDLER_abortp)                        \
  336.     exit_interruption_extent ();                    \
  337.   SIGNAL_HANDLER_RETURN ();                        \
  338. }
  339.  
  340. #else /* NEED_HANDLER_TRANSACTION */
  341.  
  342. struct handler_record
  343. {
  344.   int signo;
  345.   Tsignal_handler handler;
  346. };
  347.  
  348. #define DEFUN_STD_HANDLER(name, statement)                \
  349. static Tsignal_handler_result                        \
  350. DEFUN (name, (signo, info, pscp),                    \
  351.        int signo AND                            \
  352.        SIGINFO_T info AND                        \
  353.        struct SIGCONTEXT * pscp)                    \
  354. {                                    \
  355.   int STD_HANDLER_abortp;                        \
  356.   DECLARE_FULL_SIGCONTEXT (scp);                    \
  357.   INITIALIZE_FULL_SIGCONTEXT (pscp, scp);                \
  358.   ENTER_HANDLER (signo);                        \
  359.   STD_HANDLER_abortp = (enter_interruption_extent ());            \
  360.   transaction_begin ();                            \
  361.   {                                    \
  362.     struct handler_record * record =                    \
  363.       (dstack_alloc (sizeof (struct handler_record)));            \
  364.     (record -> signo) = signo;                        \
  365.     (record -> handler) = handler;                    \
  366.     transaction_record_action (tat_abort, ta_abort_handler, record);    \
  367.   }                                    \
  368.   statement;                                \
  369.   if (STD_HANDLER_abortp)                        \
  370.     {                                    \
  371.       transaction_abort ();                        \
  372.       exit_interruption_extent ();                    \
  373.     }                                    \
  374.   transaction_commit ();                        \
  375.   EXIT_HANDLER (signo, name);                        \
  376.   SIGNAL_HANDLER_RETURN ();                        \
  377. }
  378.  
  379. static void
  380. DEFUN (ta_abort_handler, (ap), PTR ap)
  381. {
  382.   ABORT_HANDLER ((((struct handler_record *) ap) -> signo),
  383.          (((struct handler_record *) ap) -> handler));
  384. }
  385.  
  386. #endif /* NEED_HANDLER_TRANSACTION */
  387.  
  388. #define CONTROL_B_INTERRUPT_CHAR 'B'
  389. #define CONTROL_G_INTERRUPT_CHAR 'G'
  390. #define CONTROL_U_INTERRUPT_CHAR 'U'
  391. #define CONTROL_X_INTERRUPT_CHAR 'X'
  392.  
  393. static void
  394. DEFUN (echo_keyboard_interrupt, (c, dc), cc_t c AND cc_t dc)
  395. {
  396.   if (c == (OS_ctty_disabled_char ()))
  397.     c = dc;
  398.   c &= 0177;
  399.   if (c == ALERT_CHAR)
  400.     putc (c, stdout);
  401.   else if (c < '\040')
  402.     {
  403.       putc ('^', stdout);
  404.       putc ((c + '@'), stdout);
  405.     }
  406.   else if (c == '\177')
  407.     fputs ("^?", stdout);
  408.   else
  409.     putc (c, stdout);
  410.   fflush (stdout);
  411. }
  412.  
  413. DEFUN_STD_HANDLER (sighnd_control_g,
  414.   {
  415.     echo_keyboard_interrupt ((OS_ctty_int_char ()), ALERT_CHAR);
  416.     tty_set_next_interrupt_char (CONTROL_G_INTERRUPT_CHAR);
  417.   })
  418.  
  419. DEFUN_STD_HANDLER (sighnd_control_u,
  420.   {
  421.     tty_set_next_interrupt_char (CONTROL_U_INTERRUPT_CHAR);
  422.   })
  423.  
  424. DEFUN_STD_HANDLER (sighnd_control_x,
  425.   {
  426.     tty_set_next_interrupt_char (CONTROL_X_INTERRUPT_CHAR);
  427.   })
  428.  
  429. DEFUN_STD_HANDLER (sighnd_control_b,
  430.   {
  431.     tty_set_next_interrupt_char (CONTROL_B_INTERRUPT_CHAR);
  432.   })
  433.  
  434. static void EXFUN
  435.   (interactive_interrupt_handler, (struct FULL_SIGCONTEXT * scp));
  436.  
  437. DEFUN_STD_HANDLER (sighnd_interactive,
  438.   (interactive_interrupt_handler (scp)))
  439.  
  440. void
  441. DEFUN (stop_signal_default, (signo), int signo)
  442. {
  443. #ifdef HAVE_POSIX_SIGNALS
  444.   if ((isatty (STDIN_FILENO))
  445.       && (isatty (STDOUT_FILENO))
  446.       && (! option_emacs_subprocess))
  447.   {
  448.     /* No need to handle systems without POSIX signals;
  449.        all job-control systems have them. */
  450.     sigset_t signo_mask;
  451.     sigset_t old_mask;
  452.     Tsignal_handler handler;
  453.  
  454.     /* Give the terminal back to the invoking process. */
  455.     OS_save_internal_state ();
  456.     OS_restore_external_state ();
  457.  
  458.     /* Temporarily unbind this handler. */
  459.     handler = (current_handler (signo));
  460.     INSTALL_HANDLER (signo, SIG_DFL);
  461.  
  462.     /* Perform the default action for this signal. */
  463.     UX_sigemptyset (&signo_mask);
  464.     UX_sigaddset ((&signo_mask), signo);
  465.     UX_sigprocmask (SIG_UNBLOCK, (&signo_mask), (&old_mask));
  466.     UX_kill ((UX_getpid ()), signo);
  467.     UX_sigprocmask (SIG_SETMASK, (&old_mask), 0);
  468.  
  469.     /* Rebind this handler. */
  470.     INSTALL_HANDLER (signo, handler);
  471.  
  472.     /* Get the terminal back to its original state. */
  473.     OS_save_external_state ();
  474.     OS_restore_internal_state ();
  475.   }
  476. #endif /* HAVE_POSIX_SIGNALS */
  477. }
  478.  
  479. void EXFUN ((*stop_signal_hook), (int signo));
  480.  
  481. #ifdef HAVE_POSIX_SIGNALS
  482. #  define IF_POSIX_SIGNALS(code) do code while (0)
  483. #else
  484. #  define IF_POSIX_SIGNALS(code) do {} while (0)
  485. #endif
  486.  
  487. DEFUN_STD_HANDLER (sighnd_stop,
  488.   IF_POSIX_SIGNALS(
  489.   {
  490.     sigset_t old_mask;
  491.     sigset_t jc_mask;
  492.  
  493.     if (! (UX_SC_JOB_CONTROL ()))
  494.       return;
  495.     /* Initialize the signal masks. */
  496.     UX_sigemptyset (&jc_mask);
  497.     UX_sigaddset ((&jc_mask), SIGTTOU);
  498.     UX_sigaddset ((&jc_mask), SIGTTIN);
  499.     UX_sigaddset ((&jc_mask), SIGTSTP);
  500.     UX_sigaddset ((&jc_mask), SIGSTOP);
  501.     UX_sigaddset ((&jc_mask), SIGCHLD);
  502.  
  503.     /* Block the job-control signals. */
  504.     UX_sigprocmask (SIG_BLOCK, (&jc_mask), (&old_mask));
  505.  
  506.     if (stop_signal_hook == 0)
  507.       stop_signal_default (signo);
  508.     else
  509.       (*stop_signal_hook) (signo);
  510.  
  511.     /* Restore the signal mask to its original state. */
  512.     UX_sigprocmask (SIG_SETMASK, (&old_mask), 0);
  513.   }))
  514.  
  515. void
  516. DEFUN_VOID (OS_restartable_exit)
  517. {
  518.   stop_signal_default (SIGTSTP);
  519. }
  520.  
  521. #ifdef HAVE_ITIMER
  522.  
  523. DEFUN_STD_HANDLER (sighnd_timer,
  524.   {
  525.     request_timer_interrupt ();
  526.   })
  527.  
  528. #else /* not HAVE_ITIMER */
  529.  
  530. extern void EXFUN (reschedule_alarm, (void));
  531.  
  532. DEFUN_STD_HANDLER (sighnd_timer,
  533.   {
  534.     reschedule_alarm ();
  535.     request_timer_interrupt ();
  536.   })
  537.  
  538. #endif /* HAVE_ITIMER */
  539.  
  540. DEFUN_STD_HANDLER (sighnd_save_then_terminate,
  541.   (request_suspend_interrupt ()))
  542.  
  543. DEFUN_STD_HANDLER (sighnd_terminate,
  544.   (termination_signal
  545.    ((! (option_emacs_subprocess && (signo == SIGHUP)))
  546.     ? (find_signal_name (signo))
  547.     : 0)))
  548.  
  549. DEFUN_STD_HANDLER (sighnd_fpe,
  550.   {
  551.     if (executing_scheme_primitive_p ())
  552.       error_floating_point_exception ();
  553.     trap_handler ("floating-point exception", signo, info, scp);
  554.   })
  555.  
  556. DEFUN_STD_HANDLER (sighnd_hardware_trap,
  557.   (trap_handler ("hardware fault", signo, info, scp)))
  558.  
  559. DEFUN_STD_HANDLER (sighnd_software_trap,
  560.   (trap_handler ("system software fault", signo, info, scp)))
  561.  
  562. #ifdef HAVE_NICE
  563.  
  564. #ifndef NICE_DELTA
  565. #define NICE_DELTA 5
  566. #endif
  567.  
  568. DEFUN_STD_HANDLER (sighnd_renice,
  569.   {
  570.     fprintf (stderr, "\n;;; Renicing! New nice value = %d\n",
  571.          ((nice (NICE_DELTA)) + 20));
  572.     fflush (stderr);
  573.   })
  574.  
  575. #endif /* HAVE_NICE */
  576.  
  577. /* When a child process terminates, it becomes a zombie until its
  578.    parent process calls one of the wait() routines to obtain the
  579.    child's termination status.  The SIGCHLD handler must always call
  580.    wait() or waitpid() to permit the child process's resources to be
  581.    freed. */
  582.  
  583. /* On systems with waitpid() (i.e. those that support WNOHANG) we must
  584.    loop until there are no more processes, because some of those
  585.    systems may deliver only one SIGCHLD when more than one child
  586.    terminates.  Systems without waitpid() (e.g. _SYSV) typically
  587.    provide queuing of SIGCHLD such that one SIGCHLD is delivered for
  588.    every child that terminates.  Systems that provide neither
  589.    waitpid() nor queuing are so losing that we can't win, in which
  590.    case we just hope that child terminations don't happen too close to
  591.    one another to cause problems. */
  592.  
  593. void EXFUN ((*subprocess_death_hook), (pid_t pid, wait_status_t * status));
  594.  
  595. #ifdef HAVE_WAITPID
  596. #define WAITPID(status) (UX_waitpid ((-1), (status), (WNOHANG | WUNTRACED)))
  597. #define BREAK
  598. #else
  599. #define WAITPID(status) (UX_wait (status))
  600. #define BREAK break
  601. #endif
  602.  
  603. DEFUN_STD_HANDLER (sighnd_dead_subprocess,
  604.   {
  605.     while (1)
  606.       {
  607.     wait_status_t status;
  608.     pid_t pid = (WAITPID (&status));
  609.     if (pid <= 0)
  610.       break;
  611.     if (subprocess_death_hook != 0)
  612.       (*subprocess_death_hook) (pid, (&status));
  613.     BREAK;
  614.       }
  615.   })
  616.  
  617. /* Signal Bindings */
  618.  
  619. static void
  620. DEFUN (bind_handler, (signo, handler),
  621.        int signo AND
  622.        Tsignal_handler handler)
  623. {
  624.   if ((signo != 0)
  625.       && ((handler != ((Tsignal_handler) sighnd_stop))
  626.       || (UX_SC_JOB_CONTROL ()))
  627.       && ((current_handler (signo)) == SIG_DFL))
  628.     INSTALL_HANDLER (signo, handler);
  629. }
  630.  
  631. void
  632. DEFUN_VOID (UX_initialize_signals)
  633. {
  634.   stop_signal_hook = 0;
  635.   subprocess_death_hook = 0;
  636.   initialize_signal_descriptors ();
  637.   bind_handler (SIGINT,        sighnd_control_g);
  638.   bind_handler (SIGFPE,        sighnd_fpe);
  639.   bind_handler (SIGALRM,    sighnd_timer);
  640.   bind_handler (SIGVTALRM,    sighnd_timer);
  641.   bind_handler (SIGUSR1,    sighnd_save_then_terminate);
  642. #ifdef HAVE_NICE
  643.   bind_handler (SIGUSR2,    sighnd_renice);
  644. #endif
  645.   bind_handler (SIGCHLD,    sighnd_dead_subprocess);
  646.   /* If this signal is ignored, then the system call that would have
  647.      caused it will return EPIPE instead.  This is much easier for us
  648.      to handle. */
  649.   bind_handler (SIGPIPE,    SIG_IGN);
  650.   if ((isatty (STDIN_FILENO)) || option_emacs_subprocess)
  651.     {
  652.       if (getenv ("USE_SCHEMATIK_STYLE_INTERRUPTS"))
  653.         bind_handler (SIGHUP,   sighnd_control_b);
  654.       else if (!option_emacs_subprocess)
  655.     bind_handler (SIGHUP,    sighnd_save_then_terminate);
  656.       if (getenv ("USE_SCHEMATIK_STYLE_INTERRUPTS"))
  657.         bind_handler (SIGQUIT,  sighnd_control_u);
  658.       else
  659.         bind_handler (SIGQUIT,    sighnd_interactive);
  660.       bind_handler (SIGPWR,    sighnd_save_then_terminate);
  661.       bind_handler (SIGTSTP,    sighnd_stop);
  662.       bind_handler (SIGILL,    sighnd_hardware_trap);
  663.       bind_handler (SIGTRAP,    sighnd_hardware_trap);
  664.       bind_handler (SIGBUS,    sighnd_hardware_trap);
  665.       bind_handler (SIGSEGV,    sighnd_hardware_trap);
  666.       if (getenv ("USE_SCHEMATIK_STYLE_INTERRUPTS"))
  667.         bind_handler (SIGIOT,   sighnd_control_x);
  668.       else
  669.         bind_handler (SIGIOT,    sighnd_software_trap);
  670.       bind_handler (SIGIOT,    sighnd_software_trap);
  671.       bind_handler (SIGEMT,    sighnd_software_trap);
  672.       bind_handler (SIGSYS,    sighnd_software_trap);
  673.       bind_handler (SIGABRT,    sighnd_software_trap);
  674.       bind_handler (SIGPROF,    sighnd_software_trap);
  675.     }
  676.   {
  677.     struct signal_descriptor * scan = signal_descriptors;
  678.     struct signal_descriptor * end = (scan + signal_descriptors_length);
  679.     while (scan < end)
  680.       {
  681.     if (((scan -> flags) & NOCATCH) == 0)
  682.       switch (scan -> action)
  683.         {
  684.         case dfl_terminate:
  685.           bind_handler ((scan -> signo), sighnd_terminate);
  686.           break;
  687.         case dfl_stop:
  688.           bind_handler ((scan -> signo), sighnd_stop);
  689.           break;
  690.         }
  691.     scan += 1;
  692.       }
  693.   }
  694. }
  695.  
  696. /* Interactive Interrupt Handler */
  697.  
  698. /* Under Unix, the interrupt char is NOT requested when the interrupt is
  699.    taken.
  700.  */
  701. cc_t
  702. DEFUN (OS_tty_map_interrupt_char, (int_char), cc_t int_char)
  703. {
  704.   return int_char;
  705. }
  706.  
  707. static void EXFUN (print_interactive_help, (void));
  708. static void EXFUN (print_interrupt_chars, (void));
  709. static void EXFUN (examine_memory, (void));
  710. static void EXFUN (reset_query, (struct FULL_SIGCONTEXT * scp));
  711. static void EXFUN (interactive_back_trace, (void));
  712.  
  713. #define INTERACTIVE_NEWLINE()                        \
  714. {                                    \
  715.   if (!option_emacs_subprocess)                        \
  716.     {                                    \
  717.       putc ('\n', stdout);                        \
  718.       fflush (stdout);                            \
  719.     }                                    \
  720. }
  721.  
  722. static void
  723. DEFUN (interactive_interrupt_handler, (scp), struct FULL_SIGCONTEXT * scp)
  724. {
  725.   if (!option_emacs_subprocess)
  726.     {
  727.       fputs ((OS_tty_command_beep ()), stdout);
  728.       putc ('\n', stdout);
  729.       fflush (stdout);
  730.     }
  731.   while (1)
  732.     {
  733.       if (!option_emacs_subprocess)
  734.     {
  735.       fprintf (stdout, "Interrupt option (? for help): ");
  736.       fflush (stdout);
  737.     }
  738.       switch (userio_read_char_raw ())
  739.     {
  740.     case '\002':        /* C-B */
  741.     case 'B':
  742.     case 'b':
  743.       tty_set_next_interrupt_char (CONTROL_B_INTERRUPT_CHAR);
  744.       return;
  745.     case '\003':        /* C-C */
  746.     case '\007':        /* C-G */
  747.     case 'G':
  748.     case 'g':
  749.       tty_set_next_interrupt_char (CONTROL_G_INTERRUPT_CHAR);
  750.       return;
  751.     case '\025':        /* C-U */
  752.     case 'U':
  753.     case 'u':
  754.       tty_set_next_interrupt_char (CONTROL_U_INTERRUPT_CHAR);
  755.       return;
  756.     case '\030':        /* C-X */
  757.     case 'X':
  758.     case 'x':
  759.       tty_set_next_interrupt_char (CONTROL_X_INTERRUPT_CHAR);
  760.       return;
  761.     case 'E':
  762.     case 'e':
  763.       INTERACTIVE_NEWLINE ();
  764.       examine_memory ();
  765.       return;
  766.     case 'D':
  767.     case 'd':
  768.       INTERACTIVE_NEWLINE ();
  769.       debug_edit_flags ();
  770.       return;
  771.     case 'T':
  772.     case 't':
  773.       INTERACTIVE_NEWLINE ();
  774.       interactive_back_trace ();
  775.       return;
  776.     case 'Z':
  777.     case 'z':
  778.       INTERACTIVE_NEWLINE ();
  779.       OS_restartable_exit ();
  780.       return;
  781.     case 'Q':
  782.     case 'q':
  783.       INTERACTIVE_NEWLINE ();
  784.       termination_normal (0);
  785.       return;
  786.     case '\f':
  787.       if (!option_emacs_subprocess)
  788.         {
  789.           fputs ((OS_tty_command_clear ()), stdout);
  790.           fflush (stdout);
  791.         }
  792.       return;
  793.     case 'R':
  794.     case 'r':
  795.       reset_query (scp);
  796.       return;
  797.     case 'H':
  798.     case 'h':
  799.       if (!option_emacs_subprocess)
  800.         print_interrupt_chars ();
  801.       break;
  802.     case 'I':
  803.     case 'i':
  804.       if (!option_emacs_subprocess)
  805.         {
  806.           fputs ("Ignored.  Resuming Scheme.\n", stdout);
  807.           fflush (stdout);
  808.         }
  809.       return;
  810.     case '\0':        /* C-@ */
  811.       if (errno != 0)
  812.       {
  813.         /* IO problems, assume everything scrod. */
  814.         fprintf (stderr, "Problems reading keyboard input -- Exitting.\n");
  815.         termination_eof ();
  816.       }
  817.     default:
  818.       if (!option_emacs_subprocess)
  819.         print_interactive_help ();
  820.       break;
  821.     }
  822.     }
  823. }
  824.  
  825. static enum interrupt_handler
  826. DEFUN (encode_interrupt_handler, (handler), Tsignal_handler handler)
  827. {
  828.   return
  829.     ((handler == ((Tsignal_handler) sighnd_control_g))
  830.      ? interrupt_handler_control_g
  831.      : (handler == ((Tsignal_handler) sighnd_interactive))
  832.      ? interrupt_handler_interactive
  833.      : (handler == ((Tsignal_handler) sighnd_stop))
  834.      ? interrupt_handler_stop
  835.      : (handler == ((Tsignal_handler) sighnd_terminate))
  836.      ? interrupt_handler_terminate
  837.      : (handler == ((Tsignal_handler) SIG_IGN))
  838.      ? interrupt_handler_ignore
  839.      : (handler == ((Tsignal_handler) SIG_DFL))
  840.      ? interrupt_handler_default
  841.      : interrupt_handler_unknown);
  842. }
  843.  
  844. static Tsignal_handler
  845. DEFUN (decode_interrupt_handler, (encoding), enum interrupt_handler encoding)
  846. {
  847.   return
  848.     ((encoding == interrupt_handler_control_g)
  849.      ? ((Tsignal_handler) sighnd_control_g)
  850.      : (encoding == interrupt_handler_interactive)
  851.      ? ((Tsignal_handler) sighnd_interactive)
  852.      : (encoding == interrupt_handler_stop)
  853.      ? ((Tsignal_handler) sighnd_stop)
  854.      : (encoding == interrupt_handler_terminate)
  855.      ? ((Tsignal_handler) sighnd_terminate)
  856.      : (encoding == interrupt_handler_ignore)
  857.      ? ((Tsignal_handler) SIG_IGN)
  858.      : (encoding == interrupt_handler_default)
  859.      ? ((Tsignal_handler) SIG_DFL)
  860.      : ((Tsignal_handler) 0));
  861. }
  862.  
  863. enum interrupt_handler
  864. DEFUN_VOID (OS_signal_quit_handler)
  865. {
  866.   return (encode_interrupt_handler (current_handler (SIGQUIT)));
  867. }
  868.  
  869. enum interrupt_handler
  870. DEFUN_VOID (OS_signal_int_handler)
  871. {
  872.   return (encode_interrupt_handler (current_handler (SIGINT)));
  873. }
  874.  
  875. enum interrupt_handler
  876. DEFUN_VOID (OS_signal_tstp_handler)
  877. {
  878.   return
  879.     ((UX_SC_JOB_CONTROL ())
  880.      ? (encode_interrupt_handler (current_handler (SIGTSTP)))
  881.      : interrupt_handler_ignore);
  882. }
  883.  
  884. void
  885. DEFUN (OS_signal_set_interrupt_handlers,
  886.        (quit_handler, int_handler, tstp_handler),
  887.        enum interrupt_handler quit_handler AND
  888.        enum interrupt_handler int_handler AND
  889.        enum interrupt_handler tstp_handler)
  890. {
  891.   {
  892.     Tsignal_handler handler = (decode_interrupt_handler (quit_handler));
  893.     if (handler != 0)
  894.       INSTALL_HANDLER (SIGQUIT, handler);
  895.   }
  896.   {
  897.     Tsignal_handler handler = (decode_interrupt_handler (int_handler));
  898.     if (handler != 0)
  899.       INSTALL_HANDLER (SIGINT, handler);
  900.   }
  901.   if (UX_SC_JOB_CONTROL ())
  902.     {
  903.       Tsignal_handler handler = (decode_interrupt_handler (tstp_handler));
  904.       if (handler != 0)
  905.     INSTALL_HANDLER (SIGTSTP, handler);
  906.     }
  907. }
  908.  
  909. static void
  910. DEFUN (describe_sighnd, (signo, c), int signo AND unsigned char c)
  911. {
  912.   switch (encode_interrupt_handler (current_handler (signo)))
  913.     {
  914.     case interrupt_handler_control_g:
  915.       fputs ("When typed, scheme will get the ^G character interrupt.\n",
  916.          stdout);
  917.       fputs ("The default action is to abort the running program,\n", stdout);
  918.       fputs ("and to resume the top level read-eval-print loop.\n", stdout);
  919.       break;
  920.     case interrupt_handler_interactive:
  921.       fputs ("When typed, various interrupt options are offered.\n", stdout);
  922.       fprintf (stdout, "Type %s followed by `?' for a list of options.\n",
  923.            (char_description (c, 0)));
  924.       break;
  925.     case interrupt_handler_terminate:
  926.     describe_terminate:
  927.       fputs ("When typed, scheme will terminate.\n", stdout);
  928.       break;
  929.     case interrupt_handler_stop:
  930.     describe_stop:
  931.       fputs ("When typed, scheme will suspend execution.\n", stdout);
  932.       break;
  933.     case interrupt_handler_ignore:
  934.     describe_ignore:
  935.       fputs ("When typed, this character will be ignored.\n", stdout);
  936.       break;
  937.     case interrupt_handler_default:
  938.       {
  939.     struct signal_descriptor * descriptor =
  940.       (find_signal_descriptor (signo));
  941.     if (descriptor != 0)
  942.       switch (descriptor -> action)
  943.         {
  944.         case dfl_ignore: goto describe_ignore;
  945.         case dfl_stop: goto describe_stop;
  946.         case dfl_terminate: goto describe_terminate;
  947.         }
  948.       }
  949.     default:
  950.       fputs ("When typed, this character will have an unknown effect.\n",
  951.          stdout);
  952.       break;
  953.     }
  954. }
  955.  
  956. static void
  957. DEFUN_VOID (print_interrupt_chars)
  958. {
  959.   {
  960.     unsigned char quit_char = (OS_ctty_quit_char ());
  961.     fprintf (stdout, "\n\nThe quit character is %s.\n",
  962.          (char_description (quit_char, 1)));
  963.     describe_sighnd (SIGQUIT, quit_char);
  964.   }
  965.   {
  966.     unsigned char int_char = (OS_ctty_int_char ());
  967.     fprintf (stdout, "\nThe interrupt character is %s.\n",
  968.          (char_description (int_char, 1)));
  969.     describe_sighnd (SIGINT, int_char);
  970.   }
  971.   if (UX_SC_JOB_CONTROL ())
  972.     {
  973.       unsigned char tstp_char = (OS_ctty_tstp_char ());
  974.       fprintf (stdout, "\nThe terminal stop character is %s.\n",
  975.            (char_description (tstp_char, 1)));
  976.       describe_sighnd (SIGTSTP, tstp_char);
  977.     }
  978.   putc ('\n', stdout);
  979.   fflush (stdout);
  980. }
  981.  
  982. static void
  983. DEFUN_VOID (print_interactive_help)
  984. {
  985.   fputs ("\n\n", stdout);
  986.   fputs ("^B: Enter a breakpoint loop.\n", stdout);
  987.   fputs ("^C: Goto to top level read-eval-print (REP) loop.\n", stdout);
  988.   fputs ("^L: Clear the screen.\n", stdout);
  989.   fputs ("^U: Up to previous (lower numbered) REP loop.\n", stdout);
  990.   fputs ("^X: Abort to current REP loop.\n", stdout);
  991.   fputs ("D: Debugging: change interpreter flags.\n", stdout);
  992.   fputs ("E: Examine memory location.\n", stdout);
  993.   fputs ("H: Print simple information on interrupts.\n", stdout);
  994.   fputs ("I: Ignore interrupt request.\n", stdout);
  995.   fputs ("Q: Quit instantly, killing Scheme.\n", stdout);
  996.   fputs ("R: Hard reset, possibly killing Scheme in the process.\n", stdout);
  997.   fputs ("T: Stack trace.\n", stdout);
  998.   if (UX_SC_JOB_CONTROL ())
  999.     fputs ("Z: Quit instantly, suspending Scheme.\n", stdout);
  1000.   fputs ("\n", stdout);
  1001. }
  1002.  
  1003. static void
  1004. DEFUN (invoke_soft_reset, (name), char * name)
  1005. {
  1006.   soft_reset ();
  1007.   /*NOTREACHED*/
  1008. }
  1009.  
  1010. static void
  1011. DEFUN (reset_query, (scp), struct FULL_SIGCONTEXT * scp)
  1012. {
  1013.   putc ('\n', stdout);
  1014.   fflush (stdout);
  1015.   if (WITHIN_CRITICAL_SECTION_P ())
  1016.     {
  1017.       static CONST char * reset_choices [] =
  1018.     {
  1019.       "D = delay reset until the end of the critical section",
  1020.       "N = attempt reset now",
  1021.       "P = punt reset",
  1022.       0
  1023.       };
  1024.       fprintf (stdout,
  1025.            "Scheme is executing within critical section \"%s\".\n",
  1026.            (CRITICAL_SECTION_NAME ()));
  1027.       fputs ("Resetting now is likely to kill Scheme.\n", stdout);
  1028.       fflush (stdout);
  1029.       switch (userio_choose_option
  1030.           ("Choose one of the following actions:",
  1031.            "Action -> ",
  1032.            reset_choices))
  1033.     {
  1034.     case '\0':
  1035.       /* IO problems, assume everything scrod. */
  1036.       fprintf (stderr, "Problems reading keyboard input -- exitting.\n");
  1037.       termination_eof ();
  1038.     case 'D':
  1039.       SET_CRITICAL_SECTION_HOOK (invoke_soft_reset);
  1040.       return;
  1041.     case 'N':
  1042.       CLEAR_CRITICAL_SECTION_HOOK ();
  1043.       EXIT_CRITICAL_SECTION ({});
  1044.       hard_reset (scp);
  1045.     case 'P':
  1046.     default:
  1047.       return;
  1048.     }
  1049.     }
  1050.   if (userio_confirm ("Do you really want to reset? [Y or N] "))
  1051.     hard_reset (scp);
  1052. }
  1053.  
  1054. #define USERIO_READ_LINE_OK        0
  1055. #define USERIO_READ_LINE_TOO_LONG    1
  1056. #define USERIO_READ_LINE_INPUT_FAILED    2
  1057.  
  1058. static int
  1059. DEFUN (userio_read_line, (line, size), char * line AND int size)
  1060. {
  1061.   int result = USERIO_READ_LINE_TOO_LONG;
  1062.   transaction_begin ();
  1063.   userio_buffered_input ();    /* transaction_record_action here */
  1064.   {
  1065.     char * scan = line;
  1066.     char * end = (line + size);
  1067.     while (scan < end)
  1068.     {
  1069.       char c = (userio_read_char ());
  1070.       if ((c == '\0') && (errno != 0))
  1071.       {
  1072.     /* IO problems, assume everything scrod. */
  1073.     result = USERIO_READ_LINE_INPUT_FAILED;
  1074.     break;
  1075.       }
  1076.       if (c == '\n')
  1077.     c = '\0';
  1078.       (*scan) = c;
  1079.       if (c == '\0')
  1080.       {
  1081.     result = USERIO_READ_LINE_OK;
  1082.     break;
  1083.       }
  1084.       scan += 1;
  1085.     }
  1086.   }
  1087.   transaction_commit ();
  1088.   return (result);
  1089. }
  1090.  
  1091. static void
  1092. DEFUN_VOID (examine_memory)
  1093. {
  1094.   char input_string [256];
  1095.   fputs ("Enter location to examine (0x prefix for hex): ", stdout);
  1096.   fflush (stdout);
  1097.   if ((userio_read_line (&input_string[0], (sizeof (input_string))))
  1098.       == USERIO_READ_LINE_INPUT_FAILED)
  1099.   {
  1100.     fprintf (stderr, "Problems reading keyboard input -- exiting.\n");
  1101.     termination_eof ();
  1102.   }
  1103.   {
  1104.     long input;
  1105.     if (((((input_string[0]) == '0') && ((input_string[1]) == 'x'))
  1106.      ? (sscanf ((&input_string[2]), "%lx", (&input)))
  1107.      : (sscanf (input_string, "%ld", (&input))))
  1108.     == 1)
  1109.       debug_examine_memory (input, "contents");
  1110.   }
  1111.   putc ('\n', stdout);
  1112.   fflush (stdout);
  1113. }
  1114.  
  1115. static void
  1116. DEFUN_VOID (interactive_back_trace)
  1117. {
  1118.   char input_string [256];
  1119.   fputs ("Enter the stack trace filename (default: terminal): ", stdout);
  1120.   fflush (stdout);
  1121.   if ((userio_read_line (&input_string[0], (sizeof (input_string))))
  1122.       == USERIO_READ_LINE_INPUT_FAILED)
  1123.   {
  1124.     fprintf (stderr, "Problems reading keyboard input -- exiting.\n");
  1125.     termination_eof ();
  1126.   }
  1127.   INTERACTIVE_NEWLINE ();
  1128.   if ((strlen (&input_string[0])) == 0)
  1129.     debug_back_trace (stdout);
  1130.   else
  1131.   {
  1132.     transaction_begin ();
  1133.     {
  1134.       FILE * to_dump = (fopen (&input_string[0], "w"));
  1135.       if (to_dump == ((FILE *) NULL))
  1136.       {
  1137.     printf ("Error opening \"%s\".\n", (&input_string[0]));
  1138.     transaction_abort ();
  1139.     return;
  1140.       }
  1141.       transaction_record_action (tat_always,
  1142.                  ((void EXFUN ((*), (PTR))) fclose),
  1143.                  ((PTR) to_dump));
  1144.       fprintf (stdout, "Writing the stack trace to file \"%s\" -- ",
  1145.            &input_string[0]);
  1146.       fflush (stdout);
  1147.       debug_back_trace (to_dump);
  1148.       fputs ("Done.\n", stdout);
  1149.       fflush (stdout);
  1150.     }
  1151.     transaction_commit ();
  1152.   }
  1153.   return;
  1154. }
  1155.  
  1156. #ifdef sun3
  1157.  
  1158. /* This code assumes that it is called very soon, before
  1159.    any registers except fp have been clobbered.
  1160.  
  1161.    It also assumes that it is called directly by the
  1162.    handler, so that the original fp can be found
  1163.    by indirecting through fp twice.
  1164.  
  1165.    The trampoline routine saves d0, d1, a0, and a1
  1166.    before invoking the handler.
  1167.  
  1168.    The magic constant of 276 was found by poking with adb. */
  1169.  
  1170. static void
  1171. DEFUN (sun3_save_regs, (regs), int * regs)
  1172. {
  1173.   asm ("\n\
  1174.     movel    a6@(8),a0\n\
  1175.     movel    a6@,a1\n\
  1176. \n\
  1177.     movel    a1@(276),a0@\n\
  1178.     movel    a1@(280),a0@(4)\n\
  1179.     movel    d2,a0@(8)\n\
  1180.     movel    d3,a0@(12)\n\
  1181.     movel    d4,a0@(16)\n\
  1182.     movel    d5,a0@(20)\n\
  1183.     movel    d6,a0@(24)\n\
  1184.     movel    d7,a0@(28)\n\
  1185. \n\
  1186.     movel    a1@(284),a0@(32)\n\
  1187.     movel    a1@(288),a0@(36)\n\
  1188.     movel    a2,a0@(40)\n\
  1189.     movel    a3,a0@(44)\n\
  1190.     movel    a4,a0@(48)\n\
  1191.     movel    a5,a0@(52)\n\
  1192.     movel    a1@,a0@(56)\n\
  1193.     ");
  1194. }
  1195.  
  1196. #endif /* sun3 */
  1197.  
  1198. #ifdef vax
  1199.  
  1200. static int
  1201. DEFUN_VOID (vax_get_r0)
  1202. {
  1203.   /* This is a kludge. It relies on r0 being the return value register. */
  1204.   asm ("ret");
  1205. }
  1206.  
  1207. static int *
  1208. DEFUN (vax_save_start, (regs, r0), int * regs AND int r0)
  1209. {
  1210.   asm ("movl    fp,-(sp)");
  1211.   asm ("movl    4(ap),fp");
  1212.   asm ("movl    8(ap),(fp)");
  1213.   asm ("movl    r1,4(fp)");
  1214.   asm ("movl    r2,8(fp)");
  1215.   asm ("movl    r3,12(fp)");
  1216.   asm ("movl    r4,16(fp)");
  1217.   asm ("movl    r5,20(fp)");
  1218.   asm ("movl    r6,24(fp)");
  1219.   asm ("movl    r7,28(fp)");
  1220.   asm ("movl    r8,32(fp)");
  1221.   asm ("movl    r9,36(fp)");
  1222.   asm ("movl    r10,40(fp)");
  1223.   asm ("movl    r11,44(fp)");
  1224.   asm ("movl    (sp)+,fp");
  1225.   asm ("movl    12(fp),r0");
  1226.   asm ("ret");
  1227. }
  1228.  
  1229. static void
  1230. DEFUN (vax_save_finish, (fp, pscp, scp),
  1231.        int * fp AND
  1232.        struct sigcontext * pscp AND
  1233.        struct full_sigcontext * scp)
  1234. {
  1235.   (scp -> fs_original) = pscp;
  1236. #ifndef _ULTRIX
  1237.   /* For now, ap and fp undefined. */
  1238.   ((scp -> fs_regs) [12]) = (pscp -> sc_ap);
  1239.   ((scp -> fs_regs) [13]) = (pscp -> sc_fp);
  1240. #endif
  1241.   ((scp -> fs_regs) [14]) = (pscp -> sc_sp);
  1242.   ((scp -> fs_regs) [15]) = (pscp -> sc_pc);
  1243.   {
  1244.     int reg_number = 0;
  1245.     unsigned long reg_mask = (((fp[1]) >> 16) & 0x0fff);
  1246.     int stack_index = 5;
  1247.     while (reg_mask != 0)
  1248.       {
  1249.     if ((reg_mask & 1) != 0)
  1250.       ((scp -> fs_regs) [reg_number]) = (fp[stack_index++]);
  1251.     reg_number += 1;
  1252.     reg_mask = ((reg_mask >> 1) & 0x0fff);
  1253.       }
  1254.   }
  1255. }
  1256.  
  1257. #endif /* vax */
  1258.